iT邦幫忙

2025 iThome 鐵人賽

DAY 3
0
Software Development

深入一點點認識 Git系列 第 3

Day 3-深入一點點認識 Git:什麼是 Git 物件?

  • 分享至 

  • xImage
  •  

在上一篇文章中,我們提到底層的「管路」指令會做出 blob、tree、commit 等物件,而這些正是認識 git 結構的核心觀念!

blob

全稱為 binary large object,即「二進制大型物件」,為檔案中的內容,但不包含與內容無關的元資料(metadata)。

比如說一個寫著 “Hello, world!”.txt 文字檔,blob 就只會有 Hello, world! 這些文字本身,而不會有檔案名稱、檔案建立日期、檔案大小等資訊;檔案內容與元資料兩者組成一「檔案(file)」。

每個 blob 物件都以「安全雜湊演算法 1(Secure Hash Algorithm 1, SHA-1 hash)」計算出的雜湊碼識別,值得留意的是,因為 blob 只包含檔案內容,哪怕檔案經重新命名、搬到別的資料夾等只影響元資料的操作,這個 blob 物件與其對應的雜湊碼都不會改變。

https://ithelp.ithome.com.tw/upload/images/20250903/20178513x79AZp3NA6.png

tree

表示目錄(directory)的結構,成員可包含 blob 或其他的 tree,每棵 tree 也都有自己的雜湊碼供識別。

https://ithelp.ithome.com.tw/upload/images/20250903/20178513lWil3dlme8.png
tree 物件示意圖,每個 tree 可指向一個 blob 或另一棵 tree

上述 tree 物件示意圖可理解為以下目錄結構:

https://ithelp.ithome.com.tw/upload/images/20250903/20178513stifVVWLcS.png

commit

指的是某個 tree 在特定時間點下的快照(snapshot),除了包含指向主 tree(即根目錄)的指標,亦包含作者(author)、上代(parent)、訊息(message)等該 commit 的元資料。

https://ithelp.ithome.com.tw/upload/images/20250903/20178513uZAmWbSDMv.png
commit 物件代表某主 tree 在一特定時間點下的快照

當這個 commit 指向的主 tree 中,有某個 blob 發生改變,那與該 blob 有關的 tree 都會跟著改變。

例如若把 hello_world.txt 中的驚嘆號拿掉,改為 Hello, world,則會發生以下連鎖反應:

  1. hello_world.txt 的內容改變,產生新 blob 物件,雜湊碼由 af5626b... 改為 a5c1966...
  2. 指向原 af5626b... 的 tree 改為指向 a5c1966...,因此產生新的 tree 物件,雜湊碼由 57639e7... 改為 5ea002f...
  3. 指向原 57639e7... 的 tree 改為指向 5ea002f...,因此產生新的 tree 物件,雜湊碼由 ab7c3a8... 改為 e12e0ca...
  4. 指向原 ab7c3a8... 的 commit 改為指向 e12e0ca...,因此產生新的 commit 物件,雜湊碼由 c14a9d9... 改為 3a313e6...

https://ithelp.ithome.com.tw/upload/images/20250903/20178513qMTBMfRjHV.png
將 Hello, world! 驚嘆號拿掉後,引起的連鎖反應產生新物件流程圖

至於未發生改變的 blob 物件如 f924bfa...702d670... 則不會出現新的雜湊碼,在新的 commit 物件 3a313e6... 中,若包含 f924bfa...702d670... 兩 blob 的資訊,都直接指向舊 commit e12e0ca... 中對應的 blob,舊 commit 即為新 commit 的上代。

因此,每個新 commit 中儲存的資訊僅包含「與上代 commit 不同者」,沒發生改變的 tree 或 blob 都直接指向舊 commit 裡面的就好。

https://ithelp.ithome.com.tw/upload/images/20250903/201785137FcaiFU87U.png
將 hello_world.txt 中內容改變後,產生新的 commit 變化圖

細看雜湊碼

而不管哪個物件,都會有一組識別碼,上文中提及是透過「安全雜湊演算法 1(Secure Hash Algorithm 1, SHA-1 hash)」算出來的,所以這演算法到底是什麼?

現在我們來做個實驗,請依序輸入以下指令:

  1. touch empty1.txt(建立一名為 empty1.txt 的空文字檔)
  2. touch empty2.txt(建立一名為 empty2.txt 的空文字檔)

兩個文字檔名字不同,但內容都一樣空空如也,那這兩個檔案形成的雜湊碼分別是什麼呢?

讓我們分別輸入以下兩指令,檢視兩者產生的雜湊碼:

  1. git hash-object empty1.txt(查看 empty1.txt 文字檔產生的雜湊碼)
  2. git hash-object empty2.txt(查看 empty2.txt 文字檔產生的雜湊碼)

會得到什麼呢?

https://ithelp.ithome.com.tw/upload/images/20250903/201785136NgQPpHiNf.png

哇!兩個檔名不同、內容相同的檔案,雜湊碼都是 e69de29...!怎麼會這樣?

在下一篇文章中,我們將探討雜湊碼的計算過程,以及其當中暗藏的玄機。

小結

當我們輸入上層的「瓷器」指令如 git addgit commit,其實 git 都默默地幫我們產生 blob、tree 或 commit 物件,並建立好物件之間的關係,這結構便是我們透過 git 進行版本控制的基礎。

參考資料

  1. Git Internals — Git Objects
  2. 10.2 Git Internals — Git Objects

上一篇
Day 2-深入一點點認識 Git:上層的瓷器(Porcelain)與底層的管路(Plumbing)指令
下一篇
Day 4-深入一點點認識 Git:那些 Git 物件的雜湊碼是怎麼算出來的?
系列文
深入一點點認識 Git6
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言